/**
 * 数据采集模块
 * 负责从PLC设备采集数据并进行处理
 */
const fs = require('fs');
const path = require('path');
const logger = require('../utils/logger');
const EventEmitter = require('events');

class DataCollector extends EventEmitter {
  constructor(options = {}) {
    super();
    this.options = {
      dataStoragePath: options.dataStoragePath || 'data/',
      pollInterval: options.pollInterval || 1000,
      ...options
    };
    
    this.devices = new Map();
    this.pollTimers = new Map();
    this.isRunning = false;
    
    // 确保数据存储目录存在
    if (!fs.existsSync(this.options.dataStoragePath)) {
      fs.mkdirSync(this.options.dataStoragePath, { recursive: true });
    }
  }

  /**
   * 添加设备
   * @param {string} deviceId - 设备ID
   * @param {object} adapter - PLC适配器实例
   */
  addDevice(deviceId, adapter) {
    if (this.devices.has(deviceId)) {
      logger.warn(`设备已存在，将被替换: ${deviceId}`);
    }
    
    this.devices.set(deviceId, adapter);
    logger.info(`添加设备: ${deviceId}`);
    
    // 注册设备事件
    adapter.on('error', (error) => {
      logger.error(`设备错误: ${deviceId}, ${error.message}`);
      this.emit('deviceError', { deviceId, error });
    });
    
    adapter.on('disconnected', () => {
      logger.warn(`设备断开连接: ${deviceId}`);
      this.emit('deviceDisconnected', { deviceId });
    });
    
    adapter.on('connected', () => {
      logger.info(`设备已连接: ${deviceId}`);
      this.emit('deviceConnected', { deviceId });
    });
    
    adapter.on('reconnectFailed', () => {
      logger.error(`设备重连失败: ${deviceId}`);
      this.emit('deviceReconnectFailed', { deviceId });
    });
    
    return this;
  }

  /**
   * 移除设备
   * @param {string} deviceId - 设备ID
   */
  removeDevice(deviceId) {
    if (!this.devices.has(deviceId)) {
      logger.warn(`设备不存在: ${deviceId}`);
      return false;
    }
    
    // 停止设备轮询
    this.stopDevicePolling(deviceId);
    
    // 断开设备连接
    const adapter = this.devices.get(deviceId);
    if (adapter && adapter.connected) {
      adapter.disconnect().catch(error => {
        logger.error(`断开设备连接失败: ${deviceId}, ${error.message}`);
      });
    }
    
    // 移除设备
    this.devices.delete(deviceId);
    logger.info(`移除设备: ${deviceId}`);
    
    return true;
  }

  /**
   * 启动数据采集
   */
  async start() {
    if (this.isRunning) {
      logger.warn('数据采集已在运行中');
      return;
    }
    
    logger.info('启动数据采集');
    this.isRunning = true;
    
    // 连接所有设备
    for (const [deviceId, adapter] of this.devices.entries()) {
      try {
        if (!adapter.connected) {
          await adapter.initialize();
        }
        
        // 启动设备轮询
        this.startDevicePolling(deviceId);
      } catch (error) {
        logger.error(`连接设备失败: ${deviceId}, ${error.message}`);
      }
    }
    
    this.emit('started');
  }

  /**
   * 停止数据采集
   */
  async stop() {
    if (!this.isRunning) {
      logger.warn('数据采集未运行');
      return;
    }
    
    logger.info('停止数据采集');
    this.isRunning = false;
    
    // 停止所有设备轮询
    for (const deviceId of this.devices.keys()) {
      this.stopDevicePolling(deviceId);
    }
    
    // 断开所有设备连接
    for (const [deviceId, adapter] of this.devices.entries()) {
      try {
        if (adapter.connected) {
          await adapter.disconnect();
        }
      } catch (error) {
        logger.error(`断开设备连接失败: ${deviceId}, ${error.message}`);
      }
    }
    
    this.emit('stopped');
  }

  /**
   * 启动设备轮询
   * @param {string} deviceId - 设备ID
   */
  startDevicePolling(deviceId) {
    if (this.pollTimers.has(deviceId)) {
      this.stopDevicePolling(deviceId);
    }
    
    const adapter = this.devices.get(deviceId);
    if (!adapter) {
      logger.error(`设备不存在: ${deviceId}`);
      return false;
    }
    
    if (!adapter.connected) {
      logger.error(`设备未连接: ${deviceId}`);
      return false;
    }
    
    const device = adapter.device;
    const pollInterval = device.pollInterval || this.options.pollInterval;
    
    logger.info(`启动设备轮询: ${deviceId}, 间隔: ${pollInterval}ms`);
    
    const timer = setInterval(async () => {
      try {
        const data = await adapter.readAllTags();
        const timestamp = new Date().toISOString();
        
        // 处理采集到的数据
        this.processCollectedData(deviceId, data, timestamp);
      } catch (error) {
        logger.error(`设备轮询失败: ${deviceId}, ${error.message}`);
      }
    }, pollInterval);
    
    this.pollTimers.set(deviceId, timer);
    return true;
  }

  /**
   * 停止设备轮询
   * @param {string} deviceId - 设备ID
   */
  stopDevicePolling(deviceId) {
    if (!this.pollTimers.has(deviceId)) {
      return false;
    }
    
    clearInterval(this.pollTimers.get(deviceId));
    this.pollTimers.delete(deviceId);
    logger.info(`停止设备轮询: ${deviceId}`);
    
    return true;
  }

  /**
   * 处理采集到的数据
   * @param {string} deviceId - 设备ID
   * @param {object} data - 采集到的数据
   * @param {string} timestamp - 时间戳
   */
  processCollectedData(deviceId, data, timestamp) {
    // 发出数据事件
    this.emit('data', { deviceId, data, timestamp });
    
    // 保存数据到文件
    this.saveDataToFile(deviceId, data, timestamp);
  }

  /**
   * 保存数据到文件
   * @param {string} deviceId - 设备ID
   * @param {object} data - 采集到的数据
   * @param {string} timestamp - 时间戳
   */
  saveDataToFile(deviceId, data, timestamp) {
    try {
      const date = timestamp.split('T')[0];
      const deviceDir = path.join(this.options.dataStoragePath, deviceId);
      
      // 确保设备数据目录存在
      if (!fs.existsSync(deviceDir)) {
        fs.mkdirSync(deviceDir, { recursive: true });
      }
      
      const filePath = path.join(deviceDir, `${date}.json`);
      let fileData = [];
      
      // 如果文件已存在，读取现有数据
      if (fs.existsSync(filePath)) {
        const fileContent = fs.readFileSync(filePath, 'utf8');
        try {
          fileData = JSON.parse(fileContent);
        } catch (error) {
          logger.error(`解析数据文件失败: ${filePath}, ${error.message}`);
          fileData = [];
        }
      }
      
      // 添加新数据
      fileData.push({
        timestamp,
        data
      });
      
      // 写入文件
      fs.writeFileSync(filePath, JSON.stringify(fileData, null, 2), 'utf8');
      logger.debug(`保存数据到文件: ${filePath}`);
    } catch (error) {
      logger.error(`保存数据到文件失败: ${deviceId}, ${error.message}`);
    }
  }

  /**
   * 读取历史数据
   * @param {string} deviceId - 设备ID
   * @param {string} date - 日期 (YYYY-MM-DD)
   */
  readHistoricalData(deviceId, date) {
    try {
      const filePath = path.join(this.options.dataStoragePath, deviceId, `${date}.json`);
      
      if (!fs.existsSync(filePath)) {
        logger.warn(`历史数据文件不存在: ${filePath}`);
        return null;
      }
      
      const fileContent = fs.readFileSync(filePath, 'utf8');
      return JSON.parse(fileContent);
    } catch (error) {
      logger.error(`读取历史数据失败: ${deviceId}, ${date}, ${error.message}`);
      return null;
    }
  }
}

module.exports = DataCollector;
